package com.ruoyi.bill.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import com.baomidou.lock.executor.RedissonLockExecutor;
import com.ruoyi.bill.domain.BillPort;
import com.ruoyi.bill.domain.bo.BillPortBo;
import com.ruoyi.bill.domain.vo.BillPortVo;
import com.ruoyi.bill.mapper.BillPortMapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.bill.domain.bo.BillCustomInvestBo;
import com.ruoyi.bill.domain.vo.BillCustomInvestVo;
import com.ruoyi.bill.domain.BillCustomInvest;
import com.ruoyi.bill.mapper.BillCustomInvestMapper;
import com.ruoyi.bill.service.IBillCustomInvestService;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 客户台账Service业务层处理
 *
 * @author linziheng
 * @date 2024-02-29
 */
@RequiredArgsConstructor
@Service
public class BillCustomInvestServiceImpl implements IBillCustomInvestService {

    private final BillCustomInvestMapper baseMapper;
    private final BillPortMapper billPortMapper;
    @Autowired
    private LockTemplate lockTemplate;

    /**
     * 查询客户台账
     */
    @Override
    public BillCustomInvestVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }



    /**
     * 查询客户台账列表
     */
    @Override
    public TableDataInfo<BillCustomInvestVo> queryPageList(BillCustomInvestBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<BillCustomInvest> lqw = buildQueryWrapper(bo);
        Page<BillCustomInvestVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        TableDataInfo<BillCustomInvestVo> tableDataInfo = TableDataInfo.build(result);
        tableDataInfo.setCurrCus(baseMapper.currCus(bo));
        return tableDataInfo;
    }

    /**
     * 查询客户台账列表
     */
    @Override
    public List<BillCustomInvestVo> queryList(BillCustomInvestBo bo) {
        LambdaQueryWrapper<BillCustomInvest> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<BillCustomInvest> buildQueryWrapper(BillCustomInvestBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<BillCustomInvest> lqw = Wrappers.lambdaQuery();
         if("1".equals(bo.getFinanceType())){
            lqw.eq(StringUtils.isNotBlank(bo.getFinanceType()), BillCustomInvest::getFinanceType, bo.getFinanceType())
            .or().isNull(BillCustomInvest::getFinanceType);
        }else{
            lqw.eq(StringUtils.isNotBlank(bo.getFinanceType()), BillCustomInvest::getFinanceType, bo.getFinanceType());
        }

        if("1".equals(bo.getCheckType())){
            lqw.eq(StringUtils.isNotBlank(bo.getCheckType()), BillCustomInvest::getCheckType, bo.getCheckType())
                .or().isNull(BillCustomInvest::getCheckType);
        }else{
            lqw.eq(StringUtils.isNotBlank(bo.getCheckType()), BillCustomInvest::getCheckType, bo.getCheckType());
        }
         //or放上面
        lqw.like(StringUtils.isNotBlank(bo.getHtName()), BillCustomInvest::getHtName, bo.getHtName());
        lqw.like(StringUtils.isNotBlank(bo.getMainParty()), BillCustomInvest::getMainParty, bo.getMainParty());
        lqw.like(StringUtils.isNotBlank(bo.getAccountName()), BillCustomInvest::getAccountName, bo.getAccountName());
        lqw.eq(StringUtils.isNotBlank(bo.getAccountId()), BillCustomInvest::getAccountId, bo.getAccountId());
        lqw.between(params.get("beginInvestTime") != null && params.get("endInvestTime") != null,
            BillCustomInvest::getInvestTime ,params.get("beginInvestTime"), params.get("endInvestTime"));
        lqw.between(params.get("beginAccountTime") != null && params.get("endAccountTime") != null,
            BillCustomInvest::getAccountTime ,params.get("beginAccountTime"), params.get("endAccountTime"));
        lqw.eq(StringUtils.isNotBlank(bo.getType()), BillCustomInvest::getType, bo.getType());
        lqw.eq(StringUtils.isNotBlank(bo.getOperationType()), BillCustomInvest::getOperationType, bo.getOperationType());
        lqw.like(StringUtils.isNotBlank(bo.getMedium()), BillCustomInvest::getMedium, bo.getMedium());
        lqw.eq(StringUtils.isNotBlank(bo.getBidding()), BillCustomInvest::getBidding, bo.getBidding());
        lqw.orderByDesc(BillCustomInvest::getAccountTime);
        lqw.orderByDesc(BillCustomInvest::getCreateTime);
        lqw.orderByDesc(BillCustomInvest::getIndexXn);
        return lqw;
    }

    /**
     * 新增客户台账
     */
    @Override
    public Boolean insertByBo(BillCustomInvestBo bo) {
        BillCustomInvest add = BeanUtil.toBean(bo, BillCustomInvest.class);
        validEntityBeforeSave(add);
        boolean flag = false;
        final LockInfo lockInfo = lockTemplate.lock("cus", 30000L, 5000L, RedissonLockExecutor.class);
        if (null == lockInfo) {
            throw new RuntimeException("业务处理中,请稍后再试");
        }
//        // 获取锁成功，处理业务
        try {
            //        查询客户台账信息 同账户id 同广告币 未匹配状态数据
            BillPortBo billPortBo = new BillPortBo();
            billPortBo.setAccountId(bo.getAccountId());
            billPortBo.setCurrency(bo.getCurrency());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            // 设置时区，CST通常指美国中部标准时间，可以使用TimeZone或者设置时区的偏移量
            // 使用SimpleDateFormat的format方法将Date对象转换为字符串
            String formattedDate = sdf.format(bo.getAccountTime());
            billPortBo.setAccountTimeTemp(formattedDate);
            // 输出转换后的日期字符串
            System.out.println(formattedDate);
            billPortBo.setAccountTime(bo.getAccountTime());
     //       List<BillPort> list = billPortMapper.getNoList(billPortBo);
            BillPort vo =new BillPort();
//            if(!list.isEmpty()){
//                // 查到了就是有匹配数据
//                vo = list.get(0);
//                add.setCheckType("0");
//                vo.setCheckType("0");
//                // 匹配成功则校验数据不变
//                add.setUrif(bo.getUrif());
//                add.setPnsoi(new BigDecimal(0));
//            }else{
//                //未查到 未校验数据进行计算
//                  add.setCheckType("1");
//            }
            add.setCheckType("1");
//            为什么同样的逻辑会写三遍呢   因为需求变更好几次了，最后不区分了

            if(bo.getAdvanceType().equals("预付") || bo.getAdvanceType().equals("垫款")){
                add = countCustomInves(add);
            }else if(bo.getAdvanceType().equals("转款") || bo.getAdvanceType().equals("退款")){
                add = countCustomInveszt(add);
            }else if(bo.getAdvanceType().equals("退现")){
                add = countCustomInvestx(add);
            }
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                //
            }
            flag = baseMapper.insert(add) > 0;
            vo.setPpId(add.getId());
            billPortMapper.updateById(vo);
        } finally {
            //释放锁
            lockTemplate.releaseLock(lockInfo);
        }


        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     *  退现 备款计算
     */
    public BillCustomInvest countCustomInvestx(BillCustomInvest bo){
        BillCustomInvestBo billCustomInvestBo = new BillCustomInvestBo();
//        billCustomInvestBo.setHtName(bo.getHtName());
        //客户简称改成主合同     2024年08月27日22:42:57
        billCustomInvestBo.setMainParty(bo.getMainParty());
        billCustomInvestBo.setMedium(bo.getMedium());
        BillCustomInvest billCustomInvest = new BillCustomInvest();
        List<BillCustomInvest> list = baseMapper.selectList(buildQueryWrapper(billCustomInvestBo));

        if(!list.isEmpty()){
            //获取最新一条记录
            billCustomInvest  = list.get(0);
            if(billCustomInvest.getBalance()!=null){
//              退现 备款计算 充值广告币 0 应收负数 实收负数 备款减少  这里有疑问吧 为实收和应收数量一致不
                bo.setBalance(billCustomInvest.getBalance().add(bo.getActualCash()).subtract(bo.getInCash()));
            }else{
                // 第一条记录
                bo.setBalance(new BigDecimal(0).add(bo.getActualCash()).subtract(bo.getInCash()));
            }
        }else{
//            新纪录
            bo.setBalance(new BigDecimal(0).add(bo.getActualCash()).subtract(bo.getInCash()));
        }


        return bo;
    }

    /**
     *  转款 退款 备款计算
     */
    public BillCustomInvest countCustomInveszt(BillCustomInvest bo){

        BillCustomInvestBo billCustomInvestBo = new BillCustomInvestBo();
//        billCustomInvestBo.setHtName(bo.getHtName());
        //客户简称改成主合同     2024年08月27日22:42:57
        billCustomInvestBo.setMainParty(bo.getMainParty());
        billCustomInvestBo.setMedium(bo.getMedium());
        BillCustomInvest billCustomInvest = new BillCustomInvest();
        List<BillCustomInvest> list = baseMapper.selectList(buildQueryWrapper(billCustomInvestBo));

        if(!list.isEmpty()){
            //获取最新一条记录
            billCustomInvest  = list.get(0);
            if(billCustomInvest.getBalance()!=null){
//                转款 退款 充值广告币 应收 为 负数   实收 0 备款增加

                bo.setBalance(billCustomInvest.getBalance().add(bo.getActualCash()).subtract(bo.getInCash()));
            }else{
                // 第一条记录
                bo.setBalance(new BigDecimal(0).add(bo.getActualCash()).subtract(bo.getInCash()));
            }
        }else{
//            新纪录
            bo.setBalance(new BigDecimal(0).add(bo.getActualCash()).subtract(bo.getInCash()));
        }

        return bo;
    }

    /**
     *  正常状态 预付 垫款 备款计算
     */
    public BillCustomInvest countCustomInves(BillCustomInvest bo){

        // 正常状态 预付 垫款 备款计算
        BillCustomInvestBo billCustomInvestBo = new BillCustomInvestBo();
//        billCustomInvestBo.setHtName(bo.getHtName());
        //客户简称改成主合同 与媒体    2024年08月27日22:42:57
        billCustomInvestBo.setMainParty(bo.getMainParty());
        billCustomInvestBo.setMedium(bo.getMedium());

        BillCustomInvest billCustomInvest = new BillCustomInvest();
        List<BillCustomInvest> list = baseMapper.selectList(buildQueryWrapper(billCustomInvestBo));
        if(!list.isEmpty()){
            //获取最新一条记录
            billCustomInvest  = list.get(0);
            if(billCustomInvest.getBalance()!=null){
               // 剩余备款 + 实收现金 - 应收
                bo.setBalance(billCustomInvest.getBalance().add(bo.getActualCash()).subtract(bo.getInCash()));

            }else{
                // 第一条记录
                bo.setBalance(new BigDecimal(0).add(bo.getActualCash()).subtract(bo.getInCash()));
            }
        }else{
//            新纪录
            bo.setBalance(new BigDecimal(0).add(bo.getActualCash()).subtract(bo.getInCash()));
        }

        return bo;
    }

    /**
     * 修改客户台账
     */
    @Override
    public Boolean updateByBo(BillCustomInvestBo bo) {
        BillCustomInvest update = BeanUtil.toBean(bo, BillCustomInvest.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(BillCustomInvest entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除客户台账
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        for (Long id : ids) {
            BillCustomInvestVo vo = baseMapper.selectVoById(id);
            BillCustomInvestBo bo = BeanUtil.toBean(vo, BillCustomInvestBo.class);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String formattedDate = sdf.format(bo.getAccountTime());
            bo.setAccountTime2(formattedDate);
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            bo.setCreateTime2(sdf2.format(vo.getCreateTime()));
            // 查询端口台账，相同账号归属 升序列表
            List<BillCustomInvest> uplist = baseMapper.recordListNoThis(bo);
            // 查询端口台账，相同账号归属 降序列表
            List<BillCustomInvest> downList = baseMapper.previous(bo);
            // 处理历史数据
            for (int i = 0; i < uplist.size(); i++) {
                if(i==0){
                    // 第一条记录


                    if(downList.size()>0){
                       //大于0 获取上一条记录
                        bo = BeanUtil.toBean(downList.get(0), BillCustomInvestBo.class);
                        if(uplist.get(i).getAdvanceType().equals("预付") || uplist.get(i).getAdvanceType().equals("垫款")){
                            uplist.get(i).setBalance(bo.getBalance().add(uplist.get(i).getActualCash()).subtract(uplist.get(i).getInCash()));
                        }else if(uplist.get(i).getAdvanceType().equals("转款") || uplist.get(i).getAdvanceType().equals("退款")){
                            uplist.get(i).setBalance(bo.getBalance().add(uplist.get(i).getActualCash()).subtract(uplist.get(i).getInCash()));
                        }else if(uplist.get(i).getAdvanceType().equals("退现")){
                            uplist.get(i).setBalance(bo.getBalance().add(uplist.get(i).getActualCash()).add(uplist.get(i).getInCash()));
                        }
                    }else{
                        //删除的数据为第一条记录
                        if(uplist.get(i).getAdvanceType().equals("预付") || uplist.get(i).getAdvanceType().equals("垫款")){
                            uplist.get(i).setBalance(new BigDecimal(0).add(uplist.get(i).getActualCash()).subtract(uplist.get(i).getInCash()));
                        }else if(uplist.get(i).getAdvanceType().equals("转款") || uplist.get(i).getAdvanceType().equals("退款")){
                            uplist.get(i).setBalance(new BigDecimal(0).add(uplist.get(i).getActualCash()).subtract(uplist.get(i).getInCash()));
                        }else if(uplist.get(i).getAdvanceType().equals("退现")){
                            uplist.get(i).setBalance(new BigDecimal(0).add(uplist.get(i).getActualCash()).add(uplist.get(i).getInCash()));
                        }
                    }



                }else{

                    if(uplist.get(i).getAdvanceType().equals("预付") || uplist.get(i).getAdvanceType().equals("垫款")){
                        uplist.get(i).setBalance(uplist.get(i-1).getBalance().add(uplist.get(i).getActualCash()).subtract(uplist.get(i).getInCash()));
                    }else if(uplist.get(i).getAdvanceType().equals("转款") || uplist.get(i).getAdvanceType().equals("退款")){
                        uplist.get(i).setBalance(uplist.get(i-1).getBalance().add(uplist.get(i).getActualCash()).subtract(uplist.get(i).getInCash()));
                    }else if(uplist.get(i).getAdvanceType().equals("退现")){
                        uplist.get(i).setBalance(uplist.get(i-1).getBalance().add(uplist.get(i).getActualCash()).add(uplist.get(i).getInCash()));
                    }
                }
            }
            baseMapper.deleteById(id);
            baseMapper.insertOrUpdateBatch(uplist);
        }

        return true;
    }

    /**
     * 计算货币总量
     *
     * @return 货币总量
     */
    @Override
    public Double countCurrency() {
        return baseMapper.countCurrency();
    }

    @Override
    public int getWeekList(String date){
        return baseMapper.getWeekList(date);
    }

    @Override
    public Boolean recordByBo(BillCustomInvestBo bo) {
        BillCustomInvest billCustomInvest = new BillCustomInvest();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String formattedDate = sdf.format(bo.getAccountTime());
        bo.setAccountTime2(formattedDate);
        List<BillCustomInvest> list = baseMapper.recordListDesc(bo);

        if(!list.isEmpty()){
            // 有历史记录
            billCustomInvest = list.get(0);


            if(billCustomInvest.getBalance()!=null){

                if(bo.getAdvanceType().equals("预付") || bo.getAdvanceType().equals("垫款")){
                    bo.setBalance(billCustomInvest.getBalance().add(bo.getActualCash()).subtract(bo.getInCash()));
                }else if(bo.getAdvanceType().equals("转款") || bo.getAdvanceType().equals("退款")){
                    bo.setBalance(billCustomInvest.getBalance().subtract(bo.getInCash()));
                }else if(bo.getAdvanceType().equals("退现")){
                    bo.setBalance(billCustomInvest.getBalance().add(bo.getInCash()));
                }
            }else{
                // 第一条记录
                if(bo.getAdvanceType().equals("预付") || bo.getAdvanceType().equals("垫款")){
                    bo.setBalance(new BigDecimal(0).add(bo.getActualCash()).subtract(bo.getInCash()));
                }else if(bo.getAdvanceType().equals("转款") || bo.getAdvanceType().equals("退款")){
                    bo.setBalance(new BigDecimal(0).subtract(bo.getInCash()));
                }else if(bo.getAdvanceType().equals("退现")){
                    bo.setBalance(new BigDecimal(0).add(bo.getInCash()));
                }
            }

        }else{
            // 第一条记录
            if(bo.getAdvanceType().equals("预付") || bo.getAdvanceType().equals("垫款")){
                bo.setBalance(new BigDecimal(0).add(bo.getActualCash()).subtract(bo.getInCash()));
            }else if(bo.getAdvanceType().equals("转款") || bo.getAdvanceType().equals("退款")){
                bo.setBalance(new BigDecimal(0).subtract(bo.getInCash()));
            }else if(bo.getAdvanceType().equals("退现")){
                bo.setBalance(new BigDecimal(0).add(bo.getInCash()));
            }
        }
        // 查询端口台账，相同账号归属 升序列表
        List<BillCustomInvest> uplist = baseMapper.recordListBl(bo);
        // 处理历史数据
        for (int i = 0; i < uplist.size(); i++) {
            if(i==0){
                // 第一条记录
                if(uplist.get(i).getAdvanceType().equals("预付") || uplist.get(i).getAdvanceType().equals("垫款")){
                    uplist.get(i).setBalance(bo.getBalance().add(uplist.get(i).getActualCash()).subtract(uplist.get(i).getInCash()));
                }else if(uplist.get(i).getAdvanceType().equals("转款") || uplist.get(i).getAdvanceType().equals("退款")){
                    uplist.get(i).setBalance(bo.getBalance().subtract(uplist.get(i).getInCash()));
                }else if(uplist.get(i).getAdvanceType().equals("退现")){
                    uplist.get(i).setBalance(bo.getBalance().add(uplist.get(i).getInCash()));
                }
            }else{

                if(uplist.get(i).getAdvanceType().equals("预付") || uplist.get(i).getAdvanceType().equals("垫款")){
                    uplist.get(i).setBalance(uplist.get(i-1).getBalance().add(uplist.get(i).getActualCash()).subtract(uplist.get(i).getInCash()));
                }else if(uplist.get(i).getAdvanceType().equals("转款") || uplist.get(i).getAdvanceType().equals("退款")){
                    uplist.get(i).setBalance(uplist.get(i-1).getBalance().subtract(uplist.get(i).getInCash()));
                }else if(uplist.get(i).getAdvanceType().equals("退现")){
                    uplist.get(i).setBalance(uplist.get(i-1).getBalance().add(uplist.get(i).getInCash()));
                }
            }
        }
        BillCustomInvest add = BeanUtil.toBean(bo, BillCustomInvest.class);
        uplist.add(add);
        return baseMapper.insertOrUpdateBatch(uplist);
    }

}
